/*
 *  copy source from lua-5.1.4 to learn lua implementation
 */
#include <stddef.h>

#define lfunc_c
#define LUA_CORE

#include "lua.h"

#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"

static void unlinkupval(UpVal *uv) {
  lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
  uv->u.l.next->u.l.prev = uv->u.l.prev;
  uv->u.l.prev->u.l.next = uv->u.l.next;
}

void luaF_freeupval(lua_State *L, UpVal *uv) {
  if (uv->v != &uv->u.value)
    unlinkupval(uv);
  luaM_free(L, uv);
}

void luaF_close(lua_State *L, StkId level) {
  UpVal *uv;
  global_State *g = G(L);
  while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) {
    GCObject *o = obj2gco(uv);
    lua_assert(!isblack(o) && uv->v != &uv->u.value);
    L->openupval = uv->next;
    if (isdead(g, o))
      luaF_freeupval(L, uv);
    else {
      unlinkupval(uv);
      setobj(L, &uv->u.value, uv->v);
      uv->v = &uv->u.value;
      luaC_linkupval(L, uv);
    }
  }
}

